package app.modules.cloudpivot.aspect;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.engine.component.query.api.FilterExpression;
import com.authine.cloudpivot.engine.component.query.api.FilterExpression.Op;
import com.authine.cloudpivot.engine.component.query.api.Order;
import com.authine.cloudpivot.engine.component.query.api.Sortable;
import com.authine.cloudpivot.engine.component.query.api.helper.Q;
import com.authine.cloudpivot.engine.domain.runtime.BizObject;
import com.authine.cloudpivot.engine.open.OpenEngineFactory;
import com.authine.cloudpivot.engine.open.domain.bizmodel.BizObjectQuery;
import com.authine.cloudpivot.engine.open.service.OpenEngine;

/**
 * 修改业务集成的参数 可通过业务模型动态配置
 *
 * @author LiuGangQiang Create in 2024/01/22
 */
@Aspect
@Component
public class BizBusServiceImplAspect {
    private static final Logger LOG = LoggerFactory.getLogger(BizBusServiceImplAspect.class);

    private static final String SCHEMA_CODE = "yejc_clpz";
    private static final String SERVICE_KEY = "fwbm";
    private static final String METHOD_KEY = "ffbm";
    private static final String STRATEGY_KEY = "cllj_key";
    private static final String CLSX_KEY = "clsx";
    private static final String CLLX_KEY = "cllx_key";
    private static final String CLLX_PARAMS = "params";
    private static final String CLLX_RESULT = "result";
    private static final Object POSITION_KEY = "sywz";
    private OpenEngine engine;

    @PostConstruct
    public void init() {
        engine = OpenEngineFactory.getOpenEngine();
    }

    /**
     * 定义切点
     *
     * @author LiuGangQiang Create in 2025/11/12
     */
    @Pointcut("execution(* com.authine.cloudpivot.engine.service.bizBus.BizBusServiceImpl.invoke(..))")
    public void invoke() {
    }

    @SuppressWarnings("unchecked")
    @Around("invoke()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
        /* 获取参数 第二个参数是服务编码 第三个参数是方法编码 第四个参数是请求参数 */
        if (args[1] instanceof String && args[2] instanceof String && args[3] instanceof Map) {
            String serviceCode = (String) args[1];
            String methodCode = (String) args[2];
            /* 根据服务编码和方法编码查询是否需要进行处理 */
            List<BizObject> targets = engine.listBizObjects(new BizObjectQuery() {
                private static final long serialVersionUID = 4548968483519262066L;

                @Override
                public String getSchemaCode() {
                    return SCHEMA_CODE;
                }

                @Override
                public FilterExpression getFilterExpression() {
                    return Q.and(Q.it(SERVICE_KEY, Op.Eq, serviceCode), Q.it(METHOD_KEY, Op.Eq, methodCode));
                }

                @Override
                public Sortable getSortable() {
                    return new Sortable() {
                        private static final long serialVersionUID = 1L;

                        @Override
                        public List<? extends Order> getOrders() {
                            return Arrays.asList(new Order() {
                                private static final long serialVersionUID = 1L;

                                @Override
                                public Dir getDir() {
                                    return Dir.ASC;
                                }

                                @Override
                                public String getField() {
                                    return CLSX_KEY;
                                }
                            });
                        }
                    };
                }

            });
            /* 匹配到数据证明需要进行处理 */
            if (targets != null && targets.size() > 0) {
                /* 循环处理参数 */
                targets.stream().map(BizObject::getData).filter(map -> CLLX_PARAMS.equals(map.get(CLLX_KEY))).forEach(item -> {
                    paramshandle(item, args[3]);
                });
                args[3] = new JSONObject((Map<String, Object>) args[3]);
                /* 执行业务集成调用 */
                Object result = point.proceed(args);
                /* 循环处理结果 */
                targets.stream().map(BizObject::getData).filter(map -> CLLX_RESULT.equals(map.get(CLLX_KEY))).forEach(item -> {
                    resulthandle(item, result);
                });
                /* 处理完成后返回 */
                return result;
            }

        }
        return point.proceed(args);
    }

    /**
     * 参数处理方法
     *
     * @author LiuGangQiang Create in 2025/11/15
     * @param item   策略配置
     * @param params 参数
     */
    private void paramshandle(Map<String, Object> item, Object params) {
        /* 获取策略 */
        String strategy = item.get(STRATEGY_KEY).toString();
        /* 获取索引位置 */
        String position = item.get(POSITION_KEY).toString();
        switch (strategy) {
        /* 对象转数组 */
        case "obj_to_array":
            LOG.info("===>>执行参数对象转数组逻辑 转换前数据：{}", JSON.toJSONString(params));
            objToArrays(position, params);
            LOG.info("===>>执行参数对象转数组逻辑 转换后数据：{}", JSON.toJSONString(params));
            break;
        default:
            LOG.info("===>>未实现的策略[{}]，请检查配置", strategy);
            break;
        }

    }

    /**
     * 处理结果方法
     *
     * @author LiuGangQiang Create in 2025/11/15
     * @param item   策略配置
     * @param result 结果
     */
    private void resulthandle(Map<String, Object> item, Object result) {
        /* 获取策略 */
        String strategy = item.get(STRATEGY_KEY).toString();
        /* 获取索引位置 */
        String position = item.get(POSITION_KEY).toString();
        switch (strategy) {
        /* 对象转数组 */
        case "array_to_obj":
            LOG.info("===>>执行结果数组转对象逻辑 转换前数据：{}", JSON.toJSONString(result));
            arrayToObj(position, result);
            LOG.info("===>>执行结果数组转对象逻辑 转换后数据：{}", JSON.toJSONString(result));
            break;

        default:
            LOG.info("===>>未实现的策略[{}]，请检查配置", strategy);
            break;
        }

    }

    @SuppressWarnings("unchecked")
    private void objToArrays(String position, Object params) {
        String[] keys = position.split("\\.");
        Object datas = params;
        for (int i = 0; i < keys.length - 1; i++) {
            if (datas instanceof Map) {
                datas = ((Map<String, Object>) datas).get(keys[i]);
            } else {
                LOG.info("===>>暂不支持从非Map对象中取值");
                return;
            }
        }
        if (datas instanceof Map) {
            Map<String, Object> current = (Map<String, Object>) datas;
            String key = keys[keys.length - 1];
            Object value = current.get(key);
            if (value != null && !(value instanceof List)) {
                current.put(key, Arrays.asList(value));
            }
        }
    }

    private void arrayToObj(String position, Object result) {
        String[] keys = position.split("\\.");
        if (result instanceof JSONObject) {
            List<JSONObject> currents = new ArrayList<>();
            currents.add((JSONObject) result);
            for (int i = 0; i < keys.length - 1; i++) {
                List<JSONObject> nexts = new ArrayList<>();
                for (JSONObject current : currents) {
                    Object next = current.get(keys[i]);
                    if (next instanceof JSONObject) {
                        /* 如果是 JSONObject，继续处理 */
                        nexts.add((JSONObject) next);
                    } else if (next instanceof JSONArray) {
                        /* 如果是 JSONArray，处理数组中的每个对象 */
                        JSONArray array = (JSONArray) next;
                        for (int j = 0; j < array.size(); j++) {
                            Object item = array.get(j);
                            if (item instanceof JSONObject) {
                                nexts.add((JSONObject) item);
                            }
                        }
                    } else {
                        LOG.info("===>>暂不支持从非JSONObject、JSONArray对象中提取数据");
                        return;
                    }
                }
                if (!nexts.isEmpty()) {
                    /* 别忘了赋值 */
                    currents = nexts;
                } else {
                    LOG.info("===>>需要处理的数据为空,无需处理");
                    return;
                }
            }

            /* 处理最后一个键，将数组转换为第一个元素 */
            String key = keys[keys.length - 1];
            for (JSONObject current : currents) {
                Object value = current.get(key);
                if (value instanceof JSONArray) {
                    JSONArray array = (JSONArray) value;
                    if (!array.isEmpty()) {
                        current.put(key, array.get(0));
                    } else {
                        current.put(key, null);
                    }
                }
            }
        } else {
            LOG.warn("===>>返回对象不是JSONObject而是[{}]暂时无法处理", result.getClass().getCanonicalName());
        }
    }
}
